import { Component, instantiate, MeshRenderer, Prefab, primitives, utils, Vec2, _decorator } from 'cc';
import { HeatMapPoint2D } from '../heatmap-2d_3d/HeatMapPoint2D';
import { HeatMapPoint3D } from '../heatMap-3d_2d/HeatMapPoint3D';
import { IHeatmapPoint2D, IHeatmapPoint3D } from '../heatMap-3d_2d/Render3DHeatMapPoint';

import { HiddenCanvas } from './HiddenCanvas';

const { ccclass, property } = _decorator;

interface IHeatmap2PointData {
    x: number;
    y: number;
    intensity: number;
}

@ccclass('HeatMapControl')
export class HeatMapControl extends Component {
    @property
    public segmentX = 100;

    @property
    public segmentY = 100;

    @property
    public width = 10;

    @property
    public length = 10;

    @property
    public canvasWidth = 1000;

    @property
    public canvasHeight = 1000;

    @property(Prefab)
    public heatMapPoint2D: Prefab = null;

    @property(Prefab)
    public heatMapPoint3D: Prefab = null;

    public async start() {
        this.setSegment();

        await HiddenCanvas.getInstance().init();
        HiddenCanvas.getInstance().resetCanvasSize(this.canvasWidth, this.canvasHeight);

        const heatMapData = [
            [1, 2, 3, 4, 5, 16, 7, 8, 9, 20],
            [2, 0, 3, 5, 16, 1, 40, 9, 10, 8],
            [0, 0, 3, 4, 6, 7, 30, 9, 10, 8],
            [4, 2, 3, 5, 5, 1, 30, 4, 0, 18],
            [0, 2, 3, 5, 16, 7, 30, 1, 0, 8],
            [6, 2, 3, 5, 6, 17, 1, 39, 10, 0],
        ];

        const heatMapData2 = [
            [1, 2, 30, 4, 5, 16, 0, 8, 9, 0],
            [2, 0, 18, 5, 16, 1, 10, 9, 10, 8],
            [0, 0, 30, 4, 6, 7, 0, 9, 10, 8],
            [4, 2, 30, 5, 5, 1, 0, 4, 0, 8],
            [0, 2, 10, 5, 16, 7, 0, 1, 0, 8],
            [6, 2, 3, 5, 6, 17, 1, 39, 10, 0],
        ];

        // let arr = this.get2DHeatPointPos(heatMapData);
        // this.render2D(arr);

        let arr = this.get3DHeatPointPos(heatMapData);
        this.render3D(arr);

        // let arr = this.get2DHeatPointPos(heatMapData2);
        // this.render2D(arr);

        // this.scheduleOnce(() => {
        //     let arr2 = this.getHeatPoint(heatMapData2);
        //     this.render2D(arr2);
        // }, 1);
    }

    public update(deltaTime: number) {}

    public onDestroy() {}

    public get2DHeatPointPos(arr: Array<number[]>) {
        const gridSizeX = this.canvasWidth / arr[0].length;
        const gridSizeZ = this.canvasHeight / arr.length;
        const mapCenterPos = new Vec2(this.canvasWidth / 2, this.canvasHeight / 2);

        let res: IHeatmapPoint2D[] = [];

        for (let i = 0; i < arr.length; i++) {
            for (let j = 0; j < arr[i].length; j++) {
                let x = gridSizeX * j - mapCenterPos.x + gridSizeX / 2;
                let y = gridSizeZ * i - mapCenterPos.y + gridSizeZ / 2;
                res.push({ x: x, y: -y, intensity: arr[i][j] });
            }
        }
        return res;
    }

    public get3DHeatPointPos(arr: Array<number[]>) {
        const gridSizeX = this.canvasWidth / arr[0].length;
        const gridSizeZ = this.canvasHeight / arr.length;
        const mapCenterPos = new Vec2(this.canvasWidth / 2, this.canvasHeight / 2);

        let res: IHeatmapPoint3D[] = [];

        for (let i = 0; i < arr.length; i++) {
            for (let j = 0; j < arr[i].length; j++) {
                let x = gridSizeX * j - mapCenterPos.x + gridSizeX / 2;
                let z = gridSizeZ * i - mapCenterPos.y + gridSizeZ / 2;
                res.push({ x: x, z: z, intensity: arr[i][j] });
            }
        }
        return res;
    }

    public setSegment() {
        const renderer = this.node.getComponent(MeshRenderer);
        if (!renderer) {
            return;
        }
        const plane: primitives.IGeometry = primitives.plane({
            width: this.width,
            length: this.length,
            widthSegments: this.segmentX,
            lengthSegments: this.segmentY,
        });

        renderer.mesh = utils.createMesh(plane);
    }

    public render2D(arr: IHeatmapPoint2D[]) {
        HiddenCanvas.getInstance().clear2DCanvas();
        arr.forEach((i) => {
            let heatPoint = instantiate(this.heatMapPoint2D);
            heatPoint.setPosition(i.x, i.y, 1);
            HiddenCanvas.getInstance().add2DPoint(heatPoint);
            heatPoint.getComponent(HeatMapPoint2D).setIntensity(i.intensity / 40);
        });

        const tex = HiddenCanvas.getInstance().render2D();
        const renderComp = this.node.getComponent(MeshRenderer);
        renderComp.getMaterialInstance(0).setProperty('grayTexture', tex);
    }

    public render3D(arr: IHeatmapPoint3D[]) {
        HiddenCanvas.getInstance().clear3DCanvas();
        arr.forEach((i) => {
            let heatPoint = instantiate(this.heatMapPoint3D);
            heatPoint.setPosition(i.x, 1, i.z);
            HiddenCanvas.getInstance().add3DPoint(heatPoint);
            heatPoint.getComponent(HeatMapPoint3D).setIntensity(i.intensity / 40);
        });
        const tex = HiddenCanvas.getInstance().render3D();
        const renderComp = this.node.getComponent(MeshRenderer);
        renderComp.getMaterialInstance(0).setProperty('grayTexture', tex);
    }
}
